#include "yinshu_gwwindow.h"
#include "ui_yinshu_gwwindow.h"
#include "interface/yinshu_gw.h"
#include <QTimer>
#include <QTime>
#include <json.hpp>

using namespace std;

void PullMemberVideoDataCallBack_shareScreen(void* userData, const char* pMemberId, const char* codec, unsigned char *data, int datalen, unsigned timestamp);
void PullMemberVideoDataCallBack(void* userData, const char* pMemberId, const char* codec, unsigned char *data, int datalen, unsigned timestamp);
void PullAudioDataCallBack(void* userData, const char* pMemberId, const char* codec, char *buffer, int datalen, int sample_rate, int input_channels, unsigned timestamp);


//api网关事件回调函数
void OnJoined(void* userData, ErrorCode eCode)    //Vms端用户加入成功
{
    yinshu_gwWindow* yinshu_gw=(yinshu_gwWindow*)userData;
    yinshu_gw->SetStatus("已加入");

}
void OnDisConnected(void* userData)    //Vms端用户被断开
{
    yinshu_gwWindow* yinshu_gw=(yinshu_gwWindow*)userData;
    yinshu_gw->SetStatus("已断开");
}

//role === teacher(老师) student(学生) admin(巡课) tutor(助教) visitor(旁听)
void OnNewMemberJoined(void* userData, const char* pMemberId, const char* pDisplayName, const char* role)  //新成员加入,更新成员列表
{

}

void OnMemberLeft(void* userData, const char* pMemberId, const char* pDisplayName)   //离开，删除成员列表
{
    int ii=0;
}

void OnMemberEnableVideo(void* userData, const char* pMemberId, const char* pDisplayName, VideoType type)
{
    yinshu_gwWindow* yinshu_gw=(yinshu_gwWindow*)userData;
    if(type == VideoCam)
        PullMemberVideoDataFunc(yinshu_gw->handle(), pMemberId, VideoCam, PullMemberVideoDataCallBack);
    else
        PullMemberVideoDataFunc(yinshu_gw->handle(), pMemberId, VideoScreen, PullMemberVideoDataCallBack_shareScreen);
}

void OnMemberDisableVideo(void* userData, const char* pMemberId, const char* pDisplayName, VideoType type)
{

}

void OnMemberUnMuteAudio(void* userData, const char* pMemberId, const char* pDisplayName)  //非静音，就发送声音
{
    yinshu_gwWindow* yinshu_gw=(yinshu_gwWindow*)userData;
    yinshu_gw->_memberId = pMemberId;
    PullAudioDataFunc(yinshu_gw->handle(), yinshu_gw->_memberId.c_str(), PullAudioDataCallBack);
}

void OnMemberMuteAudio(void* userData, const char* pMemberId, const char* pDisplayName)   //静音，就停发声音
{
    yinshu_gwWindow* yinshu_gw=(yinshu_gwWindow*)userData;
    yinshu_gw->_memberId = pMemberId;
    PullAudioDataFunc(yinshu_gw->handle(), yinshu_gw->_memberId.c_str(), PullAudioDataCallBack);
}

void OnRemoteModifyMedia(void* userData, const char* pKind, bool bOpen)
{

}

void OnRecvUserMessage(void* userData, const char* pHistoryMessage)
{

}

void OnSessionError(void* userData, const char* reason)
{

}

void OnRoomEnd(void* userData)
{

}

void OnMemberRoleChanged(void* userData, const char* pMemberId, const char* role)
{

}

void OnRecvSignal(void* userData, const char* method, const char* jsonStr)
{

}

void OnChangeResolution(void* userData, int width, int height)
{

}

FILE *handleVideo = NULL;
void PullMemberVideoDataCallBack(void* userData, const char* pMemberId, const char* codec, unsigned char *data, int datalen, unsigned timestamp)
{
	if(handleVideo == NULL)
	{
		char name[128] = { 0 };
		sprintf(name, "./00_SendV2vToShineVideo_%s.h264", pMemberId);
		handleVideo = fopen(name,"wb");
	}

	fwrite(data, 1, datalen, handleVideo);
	printf("============PullMemberVideoDataCallBack=====%s==%d=\n",pMemberId,timestamp);
}

void PullMemberVideoDataCallBack_shareScreen(void* userData, const char* pMemberId, const char* codec, unsigned char *data, int datalen, unsigned timestamp)
{
    printf("============PullMemberVideoDataCallBack_shareScreen=====%s==%d====datelen:%d\n",pMemberId,timestamp,datalen);
}

void PullAudioDataCallBack(void* userData, const char* pMemberId, const char* codec, char *buffer, int datalen, int sample_rate, int input_channels, unsigned timestamp)
{
    yinshu_gwWindow* yinshu_gw=(yinshu_gwWindow*)userData;
    yinshu_gw->Enqueue((uint8_t*)buffer,datalen);
}

#ifndef SHINEVV_WINDOWS
static unsigned long GetTickCount()
{
    struct timespec ts;

    clock_gettime(CLOCK_MONOTONIC, &ts);

    return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
}
#endif

void* successCallBack(std::string data, void* userdata)
{
    printf("22222222222==successCallBack==\n");
    return NULL;
}

void* failCallBack(std::string data, void* userdata)
{
    printf("1111111111111111===failCallBack=\n");
    return NULL;
}


yinshu_gwWindow::yinshu_gwWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::yinshu_gwWindow)
{
    //创建网关实例
    _shine_handle = CreateYinShuGWInstance();

    ui->setupUi(this);
    ui->serverList->addItem(QString("https://vc.shinevv.com"));
    ui->serverList->addItem(QString("https://192.168.2.224:1102"));
    ui->roomId->setText(QString("92916"));
    ui->roomPasswd->setText("556595");

    //初始化SDK
    InitSDK(_shine_handle, this, 5, OnJoined, OnDisConnected, OnNewMemberJoined, OnMemberLeft,
        OnMemberEnableVideo, OnMemberDisableVideo, OnMemberUnMuteAudio, OnMemberMuteAudio, OnRemoteModifyMedia,
        OnRecvUserMessage, OnSessionError, NULL, OnRoomEnd, OnMemberRoleChanged, OnChangeResolution, OnRecvSignal);

}

yinshu_gwWindow::~yinshu_gwWindow()
{
    //释放sdk
    ReleaseSdk(_shine_handle);
    _shine_handle=NULL;

    //处理录制
    on_stopRecord_clicked();

    delete ui;
}
//生成随机字符串
QString getRandomString(int nLen)
{
    qsrand(QDateTime::currentMSecsSinceEpoch());
    const char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int size = sizeof(ch);
    char* str = new char[nLen + 1];
    int num = 0;
    for (int nIndex = 0; nIndex < nLen; ++nIndex)
    {
        num = rand() % (size - 1);
        str[nIndex] = ch[num];
    }
    str[nLen] = '\0';
    QString res(str);
    return res;
}
void yinshu_gwWindow::on_JoinBtn_clicked()
{
    //获取当前设置api服务器
    std::string apiServer=ui->serverList->currentText().toStdString();
    std::string roomId=ui->roomId->text().toStdString();
    std::string roomPasswd=ui->roomPasswd->text().toStdString();
    _memberId = getRandomString(8).toStdString();
    //加入房间
    JoinRoom2(_shine_handle, apiServer.c_str(),roomId.c_str(),roomPasswd.c_str(), MediaType::None,
        _memberId.c_str(), "demoTest",12, "tutor");
}

void yinshu_gwWindow::SetStatus(std::string status){
    ui->status->setText(QString(status.c_str()));
}

void yinshu_gwWindow::on_leaveButton_clicked()
{
    //离开房间
    LeaveRoom(_shine_handle);
    //处理录制
    on_stopRecord_clicked();
    SetStatus("已离开");
}

//音频入队列
void yinshu_gwWindow::Enqueue(uint8_t* pcm,int len){
    if(!_recording)return;
    _pcmQueue.push(std::string((const char*)pcm,len)) ;
}

void yinshu_gwWindow::delayMs(int msec){
    QTime _Timer = QTime::currentTime().addMSecs(msec); // 在当前的时间上增加多少秒
    while( QTime::currentTime() < _Timer ) // while循环
    QCoreApplication::processEvents(QEventLoop::AllEvents, 100);// 期间在做主事件循环，就避免了阻塞
}
void yinshu_gwWindow::timerEvent(QTimerEvent *event){
    if(event->timerId()==_record_timer_id && !_pcmQueue.empty()){
        std::string pcm=_pcmQueue.front();
        _pcmQueue.pop();
        if(_fpRecord&&_recording){
            fwrite(pcm.data(),1,pcm.size(),_fpRecord);
        }
    }
}
//开始录制
void yinshu_gwWindow::on_startRecord_clicked()
{
    if(_fpRecord || _recording)return;
    _fpRecord=fopen("yinshu_gwdemo_recv.pcm","wb+");
    //每30毫秒录制一次
    _record_timer_id=startTimer(15);
    _recording=true;
}

//停止录制
void yinshu_gwWindow::on_stopRecord_clicked()
{
    if(!_recording)return;
    _recording=false;
    killTimer(_record_timer_id);
    while(!_pcmQueue.empty()){
        std::string pcm=_pcmQueue.front();
        _pcmQueue.pop();
        if(_fpRecord){
            fwrite(pcm.data(),1,pcm.size(),_fpRecord);
        }
    }
    fclose(_fpRecord);
    _fpRecord=NULL;
}

void yinshu_gwWindow::on_meetRecord_clicked()
{
    std::string strMeetRecord=ui->meetRecord->text().toStdString();
    if(strMeetRecord=="会议录制"){
        ui->meetRecord->setText(QString("停止会议录制"));
        StartRecord(this->_shine_handle,NULL);
    }if(strMeetRecord=="停止会议录制"){
        StopRecord(this->_shine_handle);
        ui->meetRecord->setText(QString("会议录制"));
    }
}

